package org.slf4j;

import org.slf4j.spi.MDCAdapter;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhehen.lu
 * @date 2025/09/29 09:50
 */
public class TtlMDCAdapter implements MDCAdapter {
    // 核心数据结构：线程安全的栈存储
    private final ThreadLocal<Map<String, Deque<String>>> mdcStack =
            ThreadLocal.withInitial(ConcurrentHashMap::new);
    private static TtlMDCAdapter mtlMDCAdapter = new TtlMDCAdapter();

    public TtlMDCAdapter() {
    }

    public static MDCAdapter getInstance() {
        return mtlMDCAdapter;
    }

    static {
        MDC.MDC_ADAPTER = mtlMDCAdapter;
    }

    // ▶ 1. 压栈操作（支持嵌套）
    @Override
    public void pushByKey(String key, String value) {
        if (key == null) throw new IllegalArgumentException("Key cannot be null");
        mdcStack.get()
                .computeIfAbsent(key, k -> new ArrayDeque<>())
                .push(value); // 压入栈顶
    }

    // ▶ 2. 弹栈操作（返回栈顶值）
    @Override
    public String popByKey(String key) {
        Deque<String> stack = mdcStack.get().get(key);
        if (stack == null || stack.isEmpty()) return null;

        String value = stack.pop();
        // 栈空时清理资源
        if (stack.isEmpty()) {
            mdcStack.get().remove(key);
        }
        return value;
    }

    // ▶ 3. 获取键对应栈的副本（安全快照）
    @Override
    public Deque<String> getCopyOfDequeByKey(String key) {
        Deque<String> stack = mdcStack.get().get(key);
        return (stack != null) ? new ArrayDeque<>(stack) : null;
    }

    // ▶ 4. 清除特定键的栈
    @Override
    public void clearDequeByKey(String key) {
        Map<String, Deque<String>> map = mdcStack.get();
        Deque<String> stack = map.get(key);
        if (stack != null) {
            stack.clear();
            map.remove(key);
        }
    }

    // ---------- 传统方法兼容（保持原有逻辑）----------
    @Override
    public void put(String key, String value) {
        // 传统put视为覆盖栈顶（或创建新栈）
        Deque<String> stack = mdcStack.get().computeIfAbsent(key, k -> new ArrayDeque<>());
        if (!stack.isEmpty()) stack.pop(); // 移除旧值
        stack.push(value);
    }

    @Override
    public String get(String key) {
        Deque<String> stack = mdcStack.get().get(key);
        return (stack != null && !stack.isEmpty()) ? stack.peek() : null;
    }

    @Override
    public void remove(String key) {
        // 复用弹栈逻辑
        popByKey(key);
    }

    @Override
    public void clear() {
        mdcStack.get().clear();
    }

    @Override
    public Map<String, String> getCopyOfContextMap() {
        Map<String, Deque<String>> originalMap = mdcStack.get();
        if (originalMap == null || originalMap.isEmpty()) {
            return Collections.emptyMap();
        }

        // ▶ 1. 创建线程安全的副本
        Map<String, String> flatMap = new HashMap<>(originalMap.size());

        // ▶ 2. 遍历所有键，提取有效值
        originalMap.forEach((key, stack) -> {
            if (stack != null && !stack.isEmpty()) {
                // 取栈顶值（即最近一次push的值）
                flatMap.put(key, stack.peek());
            }
        });

        // ▶ 3. 返回不可修改的副本（防止外部篡改）
        return Collections.unmodifiableMap(flatMap);
    }

    @Override
    public void setContextMap(Map<String, String> contextMap) {
        if (contextMap == null) {
            clear(); // 清空当前上下文
            return;
        }

        // ▶ 1. 创建新的栈存储结构
        Map<String, Deque<String>> newStackMap = new ConcurrentHashMap<>();

        // ▶ 2. 将输入Map的每个值转换为单元素栈
        contextMap.forEach((key, value) -> {
            if (key != null && value != null) {
                Deque<String> stack = new ArrayDeque<>(1);
                stack.push(value);
                newStackMap.put(key, stack);
            }
        });

        // ▶ 3. 原子性替换ThreadLocal中的Map
        mdcStack.set(newStackMap);
    }
}